
#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <fstream>
#include <cstdlib> //atoi()
#include <cassert>
#include <openssl/md5.h>

#include "oj_view.hpp" //引入网页渲染模块
#include "../common/email.hpp"

#include "../common/util.hpp" //引入common目录下的工具模块，StringUtil
#include "../common/log.hpp"  //引入common目录下的工日志模块
#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>

namespace ns_model_login
{
    using namespace ns_view; // 展开网页渲染模块
    using namespace std;
    using namespace ns_util; // 展开工具模块
    using namespace ns_log;  // 展开日志模块

    // users结构体：用于表述一个用户的信息
    struct User
    {
        std::string username; // 用户名
        std::string passwd;   // 密码
        std::string role;     // 角色
        int userid;           // 用户id，唯一
        int correctnum;
        std::string email;

        User() : username(""), passwd(""), role(""), userid(0) {}
    };

    struct CorrectQues
    {
        int number;
        std::string title;
    };

    // Question结构体：用来描述一个题目，里面保存着一个题目必要的信息
    struct Question
    {
        std::string number; // 题目编号，唯一
        std::string title;  // 题目的标题
        std::string star;   // 难度: 简单 中等 困难
        int cpu_limit;      // 题目的时间要求(S)
        int mem_limit;      // 题目的空间要去(KB)
        std::string desc;   // 题目的描述
        std::string header; // 题目预设给用户在线编辑器的代码
        std::string tail;   // 题目的测试用例，需要和header拼接，形成完整代码
    };

    const std::string oj_questions = "oj_questions"; // 数据库oj中存放题目的表名
    const std::string host = "127.0.0.1";            // mysql服务端的ip地址(本地回环)
    const std::string user = "root";                 // 访问mysql服务端的用户
    const std::string passwd = "123456";             // 访问mysql服务端的用户的密码
    const std::string db = "oj";                     // 要访问的数据库
    const int port = 3306;                           // mysql服务端的端口号

    class MysqlUtil
    {
    public:
        // 获取一个数据库连接
        static void GetMysqlConnect(MYSQL **mysql)
        {
            MYSQL *my = mysql_init(nullptr);

            if (nullptr == mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
            {
                LOG(FATAL) << "连接数据库失败!\n";
                *mysql = nullptr;
                return;
            }
            LOG(INFO) << "连接数据库成功!\n";

            mysql_set_character_set(my, "utf8");
            *mysql = my;
        }
    };

    class ModelLogin
    {
    public:
        ModelLogin(){};
        ~ModelLogin(){};

        bool GetLoginInfo(const std::string username, const std::string passwd, User &out_userinfo)
        {
            std::string sql = "select * from users where username='" + username + "' and passwd='" + passwd + "'";

            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            // 5. 使用SQL对上面指定的数据库进行操作
            if (0 != mysql_query(my, sql.c_str())) // 不为0表示sql语句执行失败
            {
                LOG(WARNING) << sql << " 查询数据库的sql语句执行失败，请尽快查看。\n";
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            // 6.2 从MYSQL_RES对象里获取行数和列数
            int rows = mysql_num_rows(res);   // 获得行数量
            int cols = mysql_num_fields(res); // 获得列数量

            if (rows == 0)
            {
                mysql_close(my);
                return false;
            }

            User user;
            for (int i = 0; i < rows; i++)
            {
                MYSQL_ROW row = mysql_fetch_row(res);
                user.userid = atoi(row[0]);
                user.username = row[1];
                user.passwd = row[2];
                user.role = row[3];

                out_userinfo = user;
            }
            mysql_close(my);
            return true;
        }

        bool IsExistUser(std::string username)
        {
            std::string sql = "select * from users where username='" + username + "'";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);

            if (rows)
            {
                mysql_close(my);
                return true;
            }
            else
            {
                mysql_close(my);
                return false;
            }
        }

        bool IsExistEmail(std::string email)
        {
            std::string sql = "select * from users where email='" + email + "'";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);

            if (rows)
            {
                mysql_close(my);
                return true;
            }
            else
            {
                mysql_close(my);
                return false;
            }
        }

        bool SetSigninInfo(const std::string user, const std::string passwd, const std::string email)
        {
            std::string sql = "insert into users(username, passwd, role, email) value('" + user + "','" + passwd + "','" + "user" + "','" + email + "')";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }
            mysql_close(my);
            return true;
        }
    };

    class ControlLogin
    {
    private:
        ModelLogin model_; // 引入model模块，提供后台数据
        View view_;        // 引入view模块，提供html渲染功能

    public:
        const static int TOKEN_OUTTIME = 1000 * 60 * 30; // token有效时间30分钟
        enum LOGIN_STATUS
        {
            LOGIN_STATUS_ERROR_USERNAME = 10, // 账户错误
            LOGIN_STATUS_ERROR_PASSWD = 11,   // 密码错误

            LOGIN_STATUS_ADMIN_SUCCESS = 1, // 管理员登陆成功
            LOGIN_STATUS_ADMIN_NOW = 2,     // 管理员已经登陆

            LOGIN_STATUS_USER_SUCCESS = -1, // 用户登陆成功
            LOGIN_STATUS_USER_NOW = -2,     // 用户已经登陆

        };

        enum SIGNIN_STATUS
        {
            SIGNIN_STATUS_SUCCESS = 0,
            SIGNIN_STATUS_FAILED,
            SIGNIN_STATUS_NOW,
            SIGNIN_STATUS_ERROR_USERNAME,
            SIGNIN_STATUS_ERROR_PASSWD,
            SIGNIN_STATUS_ERROR_EMAIL
        };

        enum IS_LOGIN
        {
            IS_LOGIN_NO = 0,
            IS_LOGIN_ADMIN,
            IS_LOGIN_USER
        };

        ControlLogin(){};
        ~ControlLogin(){};
        void Login(const std::string user, const std::string passwd, const std::string token, std::string *out_json)
        {
            // TODO 完成登陆功能

            Json::Value res;

            User userinfo;
            std::string role;
            std::string username;

            bool isexist = model_.GetLoginInfo(user, passwd, userinfo);

            if (token != "null" && TokenVerify::verify(token, user, username, role) && isexist)
            {
                std::cout << "已登录 \t" << role << std::endl;
                res["role"] = role;
                if (role == "admin")
                    res["status"] = LOGIN_STATUS::LOGIN_STATUS_ADMIN_NOW;
                else
                    res["status"] = LOGIN_STATUS::LOGIN_STATUS_USER_NOW;
            }
            else
            {
                if (!model_.IsExistUser(user))
                {
                    res["status"] = LOGIN_STATUS::LOGIN_STATUS_ERROR_USERNAME;
                }
                else if (isexist)
                {

                    time_t now = time(NULL);
                    time_t outtime = now + TOKEN_OUTTIME;

                    std::string signcode = Openssl::getHashMd5ToHex(std::to_string(userinfo.userid));

                    auto token = jwt::create()
                                     .set_issuer("auth0")
                                     .set_type("JWS")
                                     .set_payload_claim("userid", jwt::claim(std::to_string(userinfo.userid)))
                                     .set_payload_claim("role", jwt::claim(userinfo.role))
                                     .set_payload_claim("username", jwt::claim(userinfo.username))
                                     .set_payload_claim("logintime", jwt::claim(std::to_string(now)))
                                     .set_payload_claim("outtime", jwt::claim(std::to_string(outtime)))
                                     .sign(jwt::algorithm::hs256{signcode.c_str()});

                    res["role"] = userinfo.role;
                    res["token"] = token.c_str();
                    if (userinfo.role == "admin")
                        res["status"] = LOGIN_STATUS::LOGIN_STATUS_ADMIN_SUCCESS;
                    else
                        res["status"] = LOGIN_STATUS::LOGIN_STATUS_USER_SUCCESS;
                }
                else
                {
                    res["status"] = LOGIN_STATUS::LOGIN_STATUS_ERROR_PASSWD;
                }
            }

            *out_json = res.toStyledString();
        }

        void Signin(const std::string user, const std::string passwd, const std::string email, std::string *out_json)
        {
            Json::Value root;

            if (user.length() < 8 || user.length() > 16)
            {
                root["status"] = SIGNIN_STATUS::SIGNIN_STATUS_ERROR_USERNAME;
            }
            else if (passwd.length() < 6 || passwd.length() > 16)
            {
                root["status"] = SIGNIN_STATUS::SIGNIN_STATUS_ERROR_PASSWD;
            }
            else if (email.length() <= 0 || !StringUtil::IsEmail(email))
            {
                root["status"] = SIGNIN_STATUS::SIGNIN_STATUS_ERROR_EMAIL;
            }
            else
            {
                if (model_.IsExistUser(user) || model_.IsExistEmail(email))
                {
                    root["status"] = SIGNIN_STATUS::SIGNIN_STATUS_NOW;
                }
                else
                {
                    if (model_.SetSigninInfo(user, passwd, email))
                    {
                        root["status"] = SIGNIN_STATUS::SIGNIN_STATUS_SUCCESS;
                    }
                    else
                    {
                        root["status"] = SIGNIN_STATUS::SIGNIN_STATUS_FAILED;
                    }
                }
            }
            *out_json = root.toStyledString();
        }

        void IsLogin(std::string token, std::string &out_json)
        {
            Json::Value res;
            std::string username;
            std::string role;
            if (token != "null" && TokenVerify::verify(token, username, role))
            {
                res["username"] = username;
                res["role"] = role;
                if (role == "admin")
                {
                    res["status"] = IS_LOGIN::IS_LOGIN_ADMIN;
                }
                else
                {
                    res["status"] = IS_LOGIN::IS_LOGIN_USER;
                }
            }
            else
            {
                res["status"] = IS_LOGIN::IS_LOGIN_NO;
            }
            out_json = res.toStyledString();
        }
    };

    class ModelAdmin
    {
    public:
        ModelAdmin(){};
        ~ModelAdmin(){};

        bool GetUsersInfo(std::string sql, vector<User> &users)
        {
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);
            LOG(DEBUG) << "\n";
            if (0 != mysql_query(my, sql.c_str()))
            {
                LOG(WARNING) << "用户表查询失败\n";
                mysql_close(my);
                return false;
            }

            LOG(DEBUG) << "用户表查询成功\n";

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);
            int cols = mysql_num_fields(res);

            User user;

            for (int i = 0; i < rows; i++)
            {
                MYSQL_ROW row = mysql_fetch_row(res);

                user.userid = atoi(row[0]);
                user.username = row[1];
                user.passwd = row[2];
                user.role = row[3];
                user.email = row[4];
                user.correctnum = atoi(row[5]);

                users.push_back(user);

                // LOG(INFO) << user.userid << " " << user.username << " " << user.passwd << " " << user.role << "\n";
            }
            mysql_close(my);
            return true;
        }

        bool GetQuestionInfo(std::string sql, vector<Question> &questions)
        {
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);
            LOG(DEBUG) << "\n";
            if (0 != mysql_query(my, sql.c_str()))
            {
                LOG(WARNING) << "题库查询失败\n";
                mysql_close(my);
                return false;
            }

            LOG(DEBUG) << "题库查询成功\n";

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);
            int cols = mysql_num_fields(res);

            Question question;

            for (int i = 0; i < rows; i++)
            {
                MYSQL_ROW row = mysql_fetch_row(res);

                question.number = row[0];
                question.title = row[1];
                question.star = row[2];
                question.cpu_limit = atoi(row[6]);
                question.mem_limit = atoi(row[7]);
                question.desc = row[3];
                question.header = row[4];
                question.tail = row[5];

                questions.push_back(question);

                // LOG(INFO) << user.userid << " " << user.username << " " << user.passwd << " " << user.role << "\n";
            }
            mysql_close(my);
            return true;
        }

        bool DeleteQuestion(int delete_id)
        {
            std::string sql = "delete from oj_questions where number='" + std::to_string(delete_id) + "'";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);
            if (0 != mysql_query(my, sql.c_str()))
            {
                LOG(WARNING) << "删除失败\n";
                mysql_close(my);
                return false;
            }
            mysql_close(my);
            return true;
        }

        bool DeleteUser(int delete_id)
        {
            std::string sql = "delete from users where userid='" + std::to_string(delete_id) + "'";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);
            if (0 != mysql_query(my, sql.c_str()))
            {
                LOG(WARNING) << "删除失败\n";
                mysql_close(my);
                return false;
            }
            mysql_close(my);
            return true;
        }

        bool InputQuestion(Question question)
        {
            // INSERT INTO `oj`.`oj_questions` (`title`, `star`, `desc`, `header`, `tail`, `cpu_limit`, `mem_limit`) VALUES ('1', '1', '1', '1', '1', '1', '1');

            std::string sql = "INSERT INTO \
                               `oj`.`oj_questions` (`title`, `star`, `desc`, `header`, `tail`, `cpu_limit`, `mem_limit`) \
                               VALUES \
                               ('" +
                              question.title + "','" + question.star + "','" + question.desc + "','" + question.header + "','" + question.tail + "','" + std::to_string(question.cpu_limit) + "','" + std::to_string(question.mem_limit) + "')";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);
            if (0 != mysql_query(my, sql.c_str()))
            {
                LOG(WARNING) << "插入失败!\n";
                mysql_close(my);
                return false;
            }
            mysql_close(my);
            return true;
        }

        bool GetUserInfo(int userid, std::string &username, std::string &email, std::string &userdesc, int &count)
        {
            std::string sql = "select email, userdesc, correctnum,username from users where userid='" + std::to_string(userid) + "'";
            std::cout << sql << std::endl;
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);
            if (rows != 1)
            {
                mysql_close(my);
                return false;
            }
            MYSQL_ROW row = mysql_fetch_row(res);
            email = row[0];
            userdesc = row[1];
            count = atoi(row[2]);
            username = row[3];

            mysql_close(my);
            return true;
        }

        bool isEmailExist(std::string email)
        {
            std::string sql = "select email from users where email='" + email + "'";
            std::cout << sql << std::endl;
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);
            if (rows != 1)
            {
                mysql_close(my);
                return false;
            }
            mysql_close(my);
            return true;
        }

        bool IsExistUser(std::string username)
        {
            std::string sql = "select * from users where username='" + username + "'";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);

            if (rows)
            {
                mysql_close(my);
                return true;
            }
            else
            {
                mysql_close(my);
                return false;
            }
        }

        int GetCheckId(std::string email)
        {
            int checkid = RandomUtil::random_6();
            time_t timeout = time(NULL) + 5 * 60 * 1000;

            std::string sql = "insert into tmp_email(email, checkid, timeout) value('" + email + "','" + std::to_string(checkid) + "','" + std::to_string(timeout) + "')";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return -1;
            }
            mysql_close(my);
            return checkid;
        }

        bool DeleteCheckid(std::string email)
        {
            std::string sql = "delete from tmp_email where email='" + email + "'";
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            mysql_close(my);
            return true;
        }

        bool isEmailExistFromTmp(std::string email)
        {
            std::string sql = "select timeout from tmp_email where email='" + email + "'";
            std::cout << sql << std::endl;
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);
            if (rows != 1)
            {
                mysql_close(my);
                return false;
            }
            mysql_close(my);
            return true;
        }

        bool isCheckidExistFromTmp(std::string checkid, std::string email)
        {
            std::string sql = "select timeout from tmp_email where checkid='" + checkid + "' and email='" + email + "'";
            std::cout << sql << std::endl;
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);

            if (rows != 1)
            {
                mysql_close(my);
                return false;
            }

            MYSQL_ROW row = mysql_fetch_row(res);
            time_t timeout = atol(row[0]);
            time_t timenow = time(NULL);

            bool flag = timenow > timeout ? false : true;
            sql = "delete from tmp_email where email='" + email + "'";
            mysql_query(my, sql.c_str());
            mysql_close(my);
            return flag;
        }

        bool AlterPassward(std::string email, std::string newpasswd)
        {
            std::string sql = "update users set passwd='" + newpasswd + "'where email='" + email + "'";
            std::cout << sql << std::endl;
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            mysql_close(my);
            return true;
        }

        bool UpdateUserInfo(std::string newusername, int userid, std::string email, std::string userdesc)
        {
            std::string sql = "update users set username='" + newusername + "', email='" + email + "', userdesc='" + userdesc + "' where userid='" + std::to_string(userid) + "'";
            std::cout << sql << std::endl;
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            mysql_close(my);
            return true;
        }

        bool GetCorrectQues(int userid, vector<CorrectQues>& CQues)
        {
            std::string sql = "select number, title from oj_correct where userid='" + std::to_string(userid) + "'";
            std::cout << sql << std::endl;
            MYSQL *my;
            MysqlUtil::GetMysqlConnect(&my);

            if (0 != mysql_query(my, sql.c_str()))
            {
                mysql_close(my);
                return false;
            }

            MYSQL_RES *res = mysql_store_result(my);
            int rows = mysql_num_rows(res);

            CorrectQues ques;
            for (int i = 0; i < rows; i++)
            {
                MYSQL_ROW row = mysql_fetch_row(res);

                ques.number = atoi(row[0]);
                ques.title = row[1];

                CQues.push_back(ques);

                // LOG(INFO) << user.userid << " " << user.username << " " << user.passwd << " " << user.role << "\n";
            }

            mysql_close(my);
            return true;
        }
    };

    class ViewAdmin
    {
    public:
        ViewAdmin(){};
        ~ViewAdmin(){};

        const std::string template_path = "./template_html/"; // 网页模板目录路径
        const int ONE_PAGE_LINES = 10;                        // 一页10行

        void ViewHtml(std::string filename, std::string &html, std::string adminname = "")
        {
            std::string stc_html = template_path + filename + ".html";
            ctemplate::TemplateDictionary dict(filename);
            if (adminname != "")
            {
                dict.SetValue("NAME", adminname);
            }
            ctemplate::Template *tpl;
            tpl = ctemplate::Template::GetTemplate(stc_html, ctemplate::DO_NOT_STRIP);
            tpl->Expand(&html, &dict);
        }
    };

    class ControlAdmin
    {
    private:
        ModelAdmin model_; // 引入model模块，提供后台数据
        ViewAdmin view_;   // 引入view模块，提供html渲染功能

        const int ONE_PAGE_LINES = 10; // 一页10行

    private:
        bool SendEmail(std::string toEmail, int checkid)
        {
            std::cout << checkid << std::endl;
            ns_email::CSendEmail e(25, "smtp.163.com");
            e.SetFromEmail("aiguazi_ouyang@163.com");
            e.SetPassward("ONEHTSGNQVMXKHRR");
            e.SetToEmail(toEmail);
            e.SetTitle("OJ");
            e.SetContent(std::to_string(checkid));
            return e.SendEmail();
        }

    public:
        ControlAdmin(){};
        ~ControlAdmin(){};

        void LoginHtml(std::string &html)
        {
            view_.ViewHtml("login", html);
        }

        void SigninHtml(std::string &html)
        {
            view_.ViewHtml("signin", html);
        }

        void AlterUserHtml(std::string &html)
        {
            view_.ViewHtml("alteruser", html);
        }

        void AdminUserHtml(std::string &html, std::string username)
        {
            view_.ViewHtml("admin_users", html, username);
        }

        void UserHtml(std::string &html, std::string username)
        {
            view_.ViewHtml("user", html, username);
        }

        void AdminQuestionHtml(std::string &html, std::string username)
        {
            view_.ViewHtml("admin_questions", html, username);
        }

        void AdminQuestionInputHtml(std::string &html, std::string username)
        {
            view_.ViewHtml("admin_input_question", html, username);
        }

        void AlterPasswdHtml(std::string &html)
        {
            view_.ViewHtml("alterpasswd", html);
        }

        // 处理管理员用户界面的数据
        void AdminUsersInfo(int number, std::string token, std::string &out_json)
        {

            std::string username;
            std::string role;
            if (token != "null" && TokenVerify::verify(token, username, role))
            {
                if (role == "admin")
                {
                    int begin = (number - 1) * 10;

                    std::string sql = "select * from users where role <> 'admin'";
                    vector<User> users;
                    model_.GetUsersInfo(sql, users);

                    int users_size = users.size();
                    int page_number = users_size % ONE_PAGE_LINES == 0 ? users_size / ONE_PAGE_LINES : users_size / ONE_PAGE_LINES + 1;

                    Json::Value root;

                    for (int i = begin; i < begin + ONE_PAGE_LINES && i < users_size; i++)
                    {
                        Json::Value sub;
                        sub["userid"] = users[i].userid;
                        sub["username"] = users[i].username;
                        sub["passwd"] = users[i].passwd;
                        sub["role"] = users[i].role;
                        sub["correctnum"] = users[i].correctnum;
                        sub["email"] = users[i].email;

                        root["users"].append(sub);
                    }
                    root["pagesize"] = page_number;
                    root["username"] = username;
                    out_json = root.toStyledString();
                }
            }
        }

        void AdminQuestionsInfo(int number, std::string token, std::string &out_json)
        {

            std::string username;
            std::string role;
            if (token != "null" && TokenVerify::verify(token, username, role))
            {
                if (role == "admin")
                {
                    int begin = (number - 1) * 10;

                    std::string sql = "select * from oj_questions";
                    vector<Question> questions;
                    model_.GetQuestionInfo(sql, questions);

                    int questions_size = questions.size();
                    int page_number = questions_size % ONE_PAGE_LINES == 0 ? questions_size / ONE_PAGE_LINES : questions_size / ONE_PAGE_LINES + 1;

                    Json::Value root;

                    for (int i = begin; i < begin + ONE_PAGE_LINES && i < questions_size; i++)
                    {
                        Json::Value sub;
                        sub["number"] = questions[i].number;
                        sub["title"] = questions[i].title;
                        sub["star"] = questions[i].star;
                        sub["cpu_limit"] = questions[i].cpu_limit;
                        sub["mem_limit"] = questions[i].mem_limit;
                        sub["desc"] = questions[i].desc;
                        sub["header"] = questions[i].header;
                        sub["tail"] = questions[i].tail;

                        root["questions"].append(sub);
                    }
                    root["pagesize"] = page_number;
                    root["username"] = username;
                    out_json = root.toStyledString();
                }
            }
        }

        // 处理删除用户
        void AdminDeleteUser(int delete_id, std::string token)
        {
            std::string username;
            std::string role;
            if (token != "null" && TokenVerify::verify(token, username, role))
            {
                if (role == "admin")
                {
                    model_.DeleteUser(delete_id);
                }
            }
        }

        // 处理删除题目
        void AdminDeleteQuestion(int delete_id, std::string token, std::string &html)
        {
            std::string username;
            std::string role;
            if (token != "null" && TokenVerify::verify(token, username, role))
            {
                if (role == "admin")
                {
                    model_.DeleteQuestion(delete_id);
                }
            }
        }

        void AdminInputques(std::string &html, std::string token, Question question)
        {
            if (question.header.length() == 0 ||
                question.desc.length() == 0 ||
                question.cpu_limit <= 0 ||
                question.mem_limit <= 0 ||
                question.star.length() == 0 ||
                question.tail.length() == 0 ||
                question.title.length() == 0)
            {
                html = "插入失败, 填入的数据不能为空";
                return;
            }
            std::string username;
            std::string role;
            if (token != "null" && TokenVerify::verify(token, username, role))
            {
                if (role == "admin")
                {
                    model_.InputQuestion(question);
                    html = "插入成功";
                }
            }
            else
            {
                html = "插入失败";
            }
        }

        void UserInfo(std::string token, std::string &out_json)
        {
            Json::Value res;
            std::string username;
            std::string role;
            std::string email;
            std::string userdesc;
            int userid;
            int count = 0;
            if (token != "null" && TokenVerify::verify(token, userid, role))
            {
                if (role == "user")
                {
                    vector<CorrectQues> CQues;
                    model_.GetUserInfo(userid, username, email, userdesc, count);
                    model_.GetCorrectQues(userid, CQues);
                    res["email"] = email;
                    res["userdesc"] = userdesc;
                    res["username"] = username;
                    res["count"] = count;

                    for (int i = 0; i < CQues.size(); i++)
                    {
                        Json::Value sub;
                        sub["number"] = CQues[i].number;
                        sub["title"] = CQues[i].title;

                        res["ques"].append(sub);
                    }
                }
            }
            else
            {
                res["status"] = -1;
            }

            out_json = res.toStyledString();
            std::cout << out_json << std::endl;
        }

        void GetCheckId(std::string email, std::string &out_json)
        {
            Json::Value res;

            if (email != "" && !StringUtil::IsEmail(email))
            {
                res["status"] = -1;
                out_json = res.toStyledString();
                return;
            }

            if (model_.isEmailExist(email))
            {
                model_.DeleteCheckid(email);
            }
            else
            {
                res["status"] = 1;
                out_json = res.toStyledString();
                return;
            }
            // 获取验证码
            int checkid = 0;
            if ((checkid = model_.GetCheckId(email)) != -1)
            {

                if (SendEmail(email, checkid))
                    res["status"] = 0;
                else
                    res["status"] = -1;
            }
            else
            {
                res["status"] = -1;
            }
            out_json = res.toStyledString();
        }

        void CheckId(std::string email, std::string checkid, std::string &out_json)
        {
            Json::Value res;

            if (model_.isEmailExistFromTmp(email))
            {
                if (model_.isCheckidExistFromTmp(checkid, email))
                {
                    res["status"] = 0;

                    std::string en_email;
                    Openssl::AES_en(email, en_email);
                    res["email"] = en_email.c_str();
                }
                else
                {
                    res["status"] = -1;
                }
            }
            else
            {
                res["status"] = 1;
            }
            out_json = res.toStyledString();
        }

        void AlterPasswd(std::string email, std::string newpasswd, std::string alginpasswd, std::string &out_json)
        {
            Json::Value res;

            if (newpasswd != "" && newpasswd == alginpasswd && email != "")
            {
                std::string de_email;
                Openssl::AES_de(email, de_email);

                if (StringUtil::IsEmail(de_email) && model_.AlterPassward(de_email, newpasswd))
                {
                    res["status"] = 0;
                }
                else
                {
                    res["status"] = 1;
                }
            }
            else
            {
                res["status"] = 1;
            }
            out_json = res.toStyledString();
        }

        void UpdateUserInfo(std::string username, std::string email, std::string userdesc, std::string token, std::string &out_json)
        {
            Json::Value res;
            int userid;
            std::string role;

            if (username.length() < 8 || username.length() > 16)
            {
                res["status"] = 2;
                out_json = res.toStyledString();
                return;
            }
            else if (email.length() <= 0 || !StringUtil::IsEmail(email))
            {
                res["status"] = 3;
                out_json = res.toStyledString();
                return;
            }
            if (token != "null" && TokenVerify::verify(token, userid, role))
            {



                if (model_.IsExistUser(username) || model_.isEmailExist(email))
                {
                    res["status"] = 1;
                }
                else
                {
                    if (model_.UpdateUserInfo(username, userid, email, userdesc))
                    {
                        res["status"] = 0;
                    }
                    else
                    {
                        res["status"] = -1;
                    }
                }
            }
            else
            {
                res["status"] = -1;
            }
            out_json = res.toStyledString();
        }
    };
} // namespace ns_model
